/**
 * 泛型
 * 可以使用泛型来创建可重用的组件，一个组件可以支持多种类型的数据。
 */
function identity<T>(args: T): T {
    return args;
}

/*let a = identity<number>(1);
let b = identity<string>('number')*/

// 利用类型推断
let a = identity(1);
let b = identity("number");
console.log(a, b); //1 number

//获取泛型参数的长度
function getGenericLength<T>(args: T[]): number {
    return args.length;
}

let c = getGenericLength(["hello", "typescript", "world"]);
console.log(c); //3


//上面方法也可以这样写
function getGenericLength1<T>(args: Array<T>): number {
    return args.length;
}

let d = getGenericLength1([1, 2, 3, 4, 54]);
let e = getGenericLength1(["1", "2", "4"]);
console.log(d, e); // 5 3


// 泛型和接口
interface DefineLength {
    length: number;
}

function getArgsLength<T extends DefineLength>(args: T): number {
    return args.length;
}

let f = getArgsLength({length: 4, arr: [1, 2, 3]});
console.log(f);  //4

// 声明一个类型参数，且它被另一个类型参数所约束
function getProperty<T, K extends keyof T>(obj: T, key: K): unknown {
    return obj[key];
}

let g = getProperty({name: "zhangsan", age: 18}, "name");
console.log(g);  //zhangsan
//let h = getProperty({name:'zhangsan',age:18},'sex')//Argument of type '"sex"' is not assignable to parameter of type '"name" | "age"'.